package com.lzl.artisan.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lzl.artisan.common.Const;
import com.lzl.artisan.model.AccountUser;
import com.lzl.artisan.model.Result;
import com.lzl.artisan.model.User;
import com.lzl.artisan.model.dto.LoginDto;
import com.lzl.artisan.service.UserService;
import com.lzl.artisan.mapper.UserMapper;
import com.lzl.artisan.utils.JwtUtil;
import com.lzl.artisan.utils.RedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
* @author 59399
* @description 针对表【user】的数据库操作Service实现
* @createDate 2023-05-11 12:58:20
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService{
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public User getByPhone(String phone) {
        return getOne(new QueryWrapper<User>().eq("phone", phone));
    }

    @Override
    public Result login(LoginDto loginDto,boolean codeAuth) {
        //验证码校验
        if (codeAuth){
            boolean validate = this.validate(loginDto.getToken(), loginDto.getCode());
            if (!validate && codeAuth){
                return Result.fail("验证码有误");
            }
        }

        //使用Authentication的实现类
        Authentication authentication = new UsernamePasswordAuthenticationToken(loginDto.getPhone(), loginDto.getPassword());

        //手动调用方法去认证 他会自动调用UserDetailsService查 然后对比
        Authentication authenticate = authenticationManager.authenticate(authentication);
        if(Objects.isNull(authenticate)){ //说明输入错误
            throw new RuntimeException("用户名或密码错误");
        }
        //拿到用户信息 然后生成jwt返回给前端，并且将用户的信息存入redis
        AccountUser loginUser = (AccountUser)authenticate.getPrincipal(); // 这个其实就是UserDetails 也就是LoginUser
        String userId = loginUser.getUserId().toString();
        User user = getByPhone(loginDto.getPhone());
        String jwt = JwtUtil.createJWT(userId);
        redisCache.setCacheObject("login:"+userId,user);//将用户信息直接存入redis

        Map<String, String> map = new HashMap<>();
        map.put("token",jwt);
        map.put("userId",userId);
        map.put("phone", user.getPhone());
        return new Result(200,map);
    }

    @Override
    public Result register(User user,String token,String code) {
        //验证码校验
        boolean validate = this.validate(token, code);
        if (!validate){
            return Result.fail("验证码有误");
        }

        //判断有无重复的手机账号
        User userExist = this.getByPhone(user.getPhone());
        if (!StringUtils.isEmpty(userExist)){
            return Result.fail("手机号重复");
        }

        //初始化用户基本信息，保存用户信息
        user.setCreatedTime(new Date());
        user.setUpdatedTime(new Date());
        if (StringUtils.isEmpty(user.getPassword())||StringUtils.isEmpty(user.getPhone())) {
            return Result.fail("用户名或密码不能为空");
        }
        String oldPassword = user.getPassword();
        String newPassword = passwordEncoder.encode(oldPassword);
        user.setPassword(newPassword);
        boolean save = this.save(user);

        //进行自动登录
        if (save){
            return this.login(new LoginDto(user.getPhone(),oldPassword),false);
        }else{
            return Result.fail("注册失败");
        }
    }

    boolean validate(String token,String code){
        if (StringUtils.isEmpty(code) ||StringUtils.isEmpty(token)) {
            return false;
        }
        if(!code.equals(redisCache.getCacheMapValue(Const.CAPTCHA_KEY, token))) {
            return false;
        }
        // 一次性使用
        redisCache.delCacheMapValue(Const.CAPTCHA_KEY, token);
        return true;
    }
}




